package com.scatteredServer.controller;

import com.scatteredServer.common.Result;
import com.scatteredServer.exception.FileException;
import com.scatteredServer.pojo.entity.FileSave;
import com.scatteredServer.util.MinioUtils;
import io.minio.errors.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("s4/files")
@Slf4j
@Tag(name = "文件上传下载", description = "文件上传下载")
public class FilesController {

    @Resource
    private MinioUtils minioUtils;

    @Value("${minio.endpoint}")
    private String preUrl;

    @Value("${minio.bucketName}")
    private String defaultBucketName;

    @Value("${minio.defaultFilePath}")
    private String defaultFilePath;


    private boolean isSafe(MultipartFile file) {
        // 获取文件名
        String fileName = file.getOriginalFilename();
        // 检查文件名是否为空
        if (fileName == null) {
            return false;
        }
        // 检查文件扩展名是否为可执行文件常见的扩展名
        String[] executableExtensions = {".exe", ".dll", ".so", ".bat", ".sh"};
        for (String extension : executableExtensions) {
            if (fileName.toLowerCase().endsWith(extension)) {
                return false;
            }
        }
        // 如果文件类型合法，返回 true，否则返回 false
        return true;
    }

    @PostMapping("/upload")
    @Operation(summary = "①上传", description = "上传结果返回的是 访问链接前缀 以及 文件名称")
    public Result<Map<String,String>> uploadFile(@RequestPart("file") MultipartFile file) {

        boolean safe = isSafe(file);
        if(!safe){
            return Result.fail("可执行文件，不允许上传");
        }

        //文件随机重命名。
        String uuid = RandomStringUtils.randomAlphanumeric(8);
        String originalFilename = file.getOriginalFilename();
        String extension = "";
        if (originalFilename != null) {
            int lastIndex = originalFilename.lastIndexOf('.');
            if (lastIndex != -1) {
                extension = originalFilename.substring(lastIndex);
            }
        }

        String filename = uuid + extension;

        String filepath = String.format("/%s/%s", defaultFilePath, filename);
        String url;
        try {
            url = minioUtils.uploadFile(file, defaultBucketName, filepath);
        } catch (IOException | ServerException | InsufficientDataException | InternalException | XmlParserException |
                 InvalidResponseException | InvalidKeyException | NoSuchAlgorithmException | ErrorResponseException e) {
            log.error("file upload error, filepath = " + filepath, e);
            throw new FileException();
        }

        Map<String,String> map = new HashMap<>();
        map.put("prefixUrl",preUrl+"/");
        map.put("fileSaveName",url);
        map.put("fileUploadName",originalFilename);
        return Result.success(map);
    }

    @Operation(summary = "②根据文件名称进行下载", description = "根据文件名称进行下载")
    @GetMapping("/download")
    public void downloadFile(String fileName, HttpServletResponse response) {
        int i = fileName.indexOf("/");
        String bucket = fileName.substring(0, i);
        String filename = fileName.substring(i);
        try {
            minioUtils.fileDownload(bucket, filename, response);
        } catch (Exception e) {
            throw new FileException();
        }
    }

}